package com.example.base.config;

import com.example.base.enums.DateFormatEnum;
import com.example.base.utils.JacksonUtil;
import com.fasterxml.jackson.annotation.JsonAutoDetect;
import com.fasterxml.jackson.annotation.JsonInclude;
import com.fasterxml.jackson.annotation.JsonTypeInfo;
import com.fasterxml.jackson.annotation.PropertyAccessor;
import com.fasterxml.jackson.core.json.JsonWriteFeature;
import com.fasterxml.jackson.databind.DeserializationFeature;
import com.fasterxml.jackson.databind.ObjectMapper;
import com.fasterxml.jackson.databind.SerializationFeature;
import com.fasterxml.jackson.databind.jsontype.impl.LaissezFaireSubTypeValidator;
import com.fasterxml.jackson.datatype.jsr310.JavaTimeModule;
import com.fasterxml.jackson.datatype.jsr310.deser.LocalDateDeserializer;
import com.fasterxml.jackson.datatype.jsr310.deser.LocalDateTimeDeserializer;
import com.fasterxml.jackson.datatype.jsr310.ser.LocalDateSerializer;
import com.fasterxml.jackson.datatype.jsr310.ser.LocalDateTimeSerializer;
import org.springframework.beans.factory.InitializingBean;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.http.converter.json.Jackson2ObjectMapperBuilder;

import java.time.LocalDate;
import java.time.LocalDateTime;
import java.util.TimeZone;

/**
 * json 配置
 */
@Configuration
public class JacksonConfig implements InitializingBean {

    private ObjectMapper objectMapper(){
        JavaTimeModule javaTimeModule = new JavaTimeModule();
        javaTimeModule.addSerializer(LocalDateTime.class, new LocalDateTimeSerializer(DateFormatEnum.NYR_SFM.getFormatter()));
        javaTimeModule.addSerializer(LocalDate.class, new LocalDateSerializer(DateFormatEnum.NYR.getFormatter()));

        javaTimeModule.addDeserializer(LocalDateTime.class, new LocalDateTimeDeserializer(DateFormatEnum.NYR_SFM.getFormatter()));
        javaTimeModule.addDeserializer(LocalDate.class, new LocalDateDeserializer(DateFormatEnum.NYR.getFormatter()));

        ObjectMapper objectMapper = Jackson2ObjectMapperBuilder.json().modules(javaTimeModule).build();
        // 设置时区
        objectMapper.setTimeZone(TimeZone.getTimeZone("GMT+8"));
        // 默认序列化 不管属性值是否为空 都进行序列化
        objectMapper.setSerializationInclusion(JsonInclude.Include.ALWAYS);
        //序列化所有访问修饰符属性
        objectMapper.setVisibility(PropertyAccessor.ALL, JsonAutoDetect.Visibility.ANY);
        // 在遇到未知属性的时候不抛出异常
        objectMapper.disable(DeserializationFeature.FAIL_ON_UNKNOWN_PROPERTIES);
        // 日期序列化字符串不是时间戳
        objectMapper.disable(SerializationFeature.WRITE_DATES_AS_TIMESTAMPS);
        // 空字符串("")转换为null
        objectMapper.enable(DeserializationFeature.ACCEPT_EMPTY_STRING_AS_NULL_OBJECT);
        // 强制转义非ASCII字符
        objectMapper.configure(JsonWriteFeature.ESCAPE_NON_ASCII.mappedFeature(), true);
        return objectMapper;
    }

    /**
     * 全局默认的对象序列化配置
     * @return
     */
    @Bean
    public ObjectMapper serializingObjectMapper() {
        return objectMapper();
    }

    /**
     * 全局默认的对象序列化工具类
     * @throws Exception
     */
    @Override
    public void afterPropertiesSet() throws Exception {
        ObjectMapper mapper = objectMapper();
        //工具类
        JacksonUtil.setMapper(mapper);
    }

    /**
     * 序列化添加类型信息
     * @return
     */
    public ObjectMapper activateDefaultTyping(){
        ObjectMapper mapper = objectMapper();
        //序列化添加类型信息
        mapper.activateDefaultTyping(LaissezFaireSubTypeValidator.instance, ObjectMapper.DefaultTyping.NON_FINAL, JsonTypeInfo.As.PROPERTY);
        return mapper;
    }
}
